package com.winai.launcher.utils;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;

import android.app.Application;

import androidx.annotation.NonNull;

import com.winai.launcher.DataSender;
import com.winai.launcher.bean.requestBean.UseInfoBean;
import com.winai.launcher.collector.DataCollector;

import org.json.JSONArray;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;

/**
 * 作者：康少
 * 时间：2020/4/13 0013
 * 说明：对外暴露的工具类——用户行为收集
 */
public class AppCollectUtil {
    private static final String TAG = "用户行为统计 AppCollectUtil";

    private Context mContext;

    private boolean isSuccess;//是否成功

    /**
     * AppCollectUtil单例
     */
//    private static AppCollectUtil sInstance;
    /**
     * 数据存入几条后发送
     */
    private int dataSizeSend = 1;

    /**
     * 用于储存要规避的View；
     */
    private ArrayList<View> mAvoidListView;
    /**
     * 数据收集接口。
     * Object to collect data.
     */
    private DataCollector mCollector;
    /**
     * 并发条件下的锁。
     * LOCK for sync
     */
    private final String LOCK = "lock";
    /**
     * 获取该页面View的层次栈。
     * Stack used to store view
     */
    private Stack<View> mViewStack;


    /**
     * 行为JSON列表。
     * List of JSON used for user behaviors
     */
    private List<UseInfoBean> mArray;

    /**
     * 前一个加载的页面，用来判断本次加载页面是否同前一次一样，避免重复收集。
     * previous loaded activity stored to avoid to collect again
     */
    private String mPrePageName;
    /**
     * 数据发送接口。
     * Object to send collected data.
     */
    private DataSender mSender;
    //用于判断是否进入后台
    private static int sessionDepth = 0;


    //监听器
    AdapterView.OnItemClickListener onItemClickListener = null;

    private View firstDown;


    private enum MyEnumSingleton {
        INSTANCE;
        private AppCollectUtil appCollectUtil;

        private MyEnumSingleton() {
            appCollectUtil = new AppCollectUtil();
        }

        public AppCollectUtil getResource() {
            return appCollectUtil;
        }
    }

    public static AppCollectUtil getInstance() {
        return MyEnumSingleton.INSTANCE.getResource();
    }
    /**
     * 必须为单例，一个应用只存在一个实例。
     *
     * @return Queen实例
     */
//        public static AppCollectUtil getInstance(Context context) {
//            if (sInstance == null) {
//                sInstance = new AppCollectUtil(context);
//            }
//        return sInstance;
//    }

    /**
     * app工具类初始化
     * Initiation of Queen;
     */
//    private AppCollectUtil(Context context) {
//
////        mObserved = new Observed();
//    }

    /**
     * 初始化一些数据
     *
     * @param application
     */
    public void init(Application application) {
        mCollector = new DataCollector();
        mArray = new ArrayList<>();
        mViewStack = new Stack<View>();
        mAvoidListView = new ArrayList<>();//用于储存要规避的View；
        mContext = application;

        mSender = new DataSender(application);
    }

    /**
     * 收集Activity状态
     * Activity status obtaining
     *
     * @param activityName  activity的标志;mark;
     * @param activityTitle activity的标题; title;
     * @param activityTag   activity的备注; tag;
     * @param isOpen        activity的状态（打开和关闭）; status(open or closed);
     * @param context
     * @param from          来自哪里 1 onstart() 2 onstop()
     */
    @SuppressLint("HandlerLeak")
    public void activityDataCollect(String activityName, String activityTitle, String activityTag,
                                    boolean isOpen, Context context, int from) {


        int type = isBackstace(from);
        if (isOpen) {
            if (activityName.equals(mPrePageName)) { //同一个界面不可能启动两次，判断为重复接口
                return;
            }
            mPrePageName = activityName;
        } else {
            mPrePageName = "";
        }
        synchronized (LOCK) {
            if (isOpen) {
                mArray = mCollector.activityOpenDataCollect(context, mArray, activityName, activityTitle, activityTag, type, "");
            } else {
                mArray = mCollector.activityCloseDataCollect(context, mArray, activityName, activityTitle, activityTag, type, "");
            }
            bufferFullSend(type);
        }
    }


    private int isBackstace(int from) {
        int type = 0;
        if (1 == from) {

            if (sessionDepth == 0) {
                // 从后台返回
                Log.d(TAG, "从后台返回");
                type = 1;
            }
            sessionDepth++;
        }
        if (2 == from) {
            if (sessionDepth > 0)
                sessionDepth--;
            if (sessionDepth == 0) {
                // 进入后台
                Log.d(TAG, "进入后台");
                type = 2;
            }
        }
        return type;
    }

    /**
     * 发送数据接口
     *
     * @param array json动作列表
     */
    public void sendData(List<UseInfoBean> array) {
        mSender.sendData(array);
    }

    /**
     * 识别在View上所进行的动作
     * Get the operation on the view.
     *
     * @param ev      动作; Operation;
     * @param myView  执行动作的View; View on the screen;
     * @param context
     */
    public void recognizeViewEvent(MotionEvent ev, View myView, Context context) {

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                Log.d(TAG, "==================================== MotionEvent.ACTION_DOWN");

                try {
                    mViewStack = new Stack<>();
                    final float pressX = ev.getRawX();
                    final float pressY = ev.getRawY();
                    findViewAtPosition(myView, (int) pressX, (int) pressY);
                    if (mViewStack.isEmpty()) {
                        firstDown = null;
                        return;
                    }
                    firstDown = mViewStack.peek();
                    Log.d(TAG, "action downview = " + firstDown);
                } catch (Exception e) {
                    Log.e(TAG, "recognizeViewEvent: unknown error");
                }

                break;
            }
            case MotionEvent.ACTION_UP: {
                Log.d(TAG, "====================================MotionEvent.ACTION_UP");
                mViewStack = new Stack<View>();
                final float x = ev.getRawX();
                final float y = ev.getRawY();
                findViewAtPosition(myView, (int) x, (int) y);
                if (mViewStack.isEmpty()) {
                    return;
                }

                View view = ignoreView();
                if (!mViewStack.isEmpty() && mViewStack.size() != 0) {
                    View actionup = mViewStack.get(0);
                    Log.d(TAG, "action actionup = " + actionup);
                    Log.d(TAG, "view = " + view);

                }
                if (null == view) {
                    return;
                }
            }
            break;
        }
    }


    /**
     * 忽略View，不搜集该View上的动作
     * Ignore the view which is inserted in the avoided view list.
     *
     * @return
     */
    private View ignoreView() {
        View view = mViewStack.pop();
        while (isAvoidView(view) && !mViewStack.isEmpty()) {
            view = mViewStack.pop();
        }
        if (isAvoidView(view)) {
            return null;
        }
        return view;
    }

    /**
     * 判断View是否在avoid View list上
     * Check whether the view is in the avoided view list;
     *
     * @param view
     * @return
     */
    private boolean isAvoidView(View view) {
        Iterator<View> i = mAvoidListView.iterator();
        while (i.hasNext()) {
            View avoidView = i.next();
            if (view == avoidView) {
                return true;
            }
        }
        return false;
    }

    /**
     * 通过用户动作的范围查找相应的View
     * find view that the user interacts.
     *
     * @param parent 最上层View
     * @param x      动作触摸点x坐标
     * @param y      动作触摸点y坐标
     */
    private void findViewAtPosition(View parent, int x, int y) {
        int length = 1;
        Rect rect = new Rect();
        parent.getGlobalVisibleRect(rect);
        if (parent instanceof ViewGroup) {
            length = ((ViewGroup) parent).getChildCount();
        }
        for (int i = 0; i < length; i++) {
            if (parent instanceof ViewGroup) {

                if (View.VISIBLE == parent.getVisibility()) {
                    View child = ((ViewGroup) parent).getChildAt(i);
                    findViewAtPosition(child, x, y);
                }
            } else {
                if (rect.contains(x, y)) {
                    if (View.VISIBLE == parent.getVisibility() && parent.isClickable()) {
                        mViewStack.push(parent);
                    }
                }
            }

        }

        if (parent.isClickable()
                && rect.contains(x, y)
                && View.VISIBLE == parent.getVisibility()) {
            mViewStack.push(parent);
        }
    }


    /**
     * Json列表满dataSizeSend条随即发送
     * check whether the json array is full(10 pic)
     */
    private void bufferFullSend(int type) {
        //判断是否列表满dataSizeSend条
        if (dataSizeSend <= mArray.size()) {
            sendData(mArray);
            //发送
            Log.d(TAG, "type = " + type + "\n发送数据 = " + mArray.toString());
            mArray = null;
            mArray = new ArrayList<>();
        }
    }

}
